---
title: "Concurrency & Asynchronous Model"
description: "Learn Rust's concurrency, asynchronous model, and multi-threading safety, contrasting with JavaScript's event loop mechanism"
---

# Concurrency & Asynchronous Model

## 📖 Learning Objectives

Understand Rust's concurrency model, including multi-threading, asynchronous programming, and thread safety mechanisms, contrasting with JavaScript's single-threaded event loop model.

---

## 🎯 Execution Model Comparison

### JavaScript's Event Loop

JavaScript uses a single-threaded event loop model:

<UniversalEditor title="JavaScript Event Loop" compare={true}>
```javascript !! js
// JavaScript Single-threaded Event Loop
console.log("Start execution");

// Synchronous code
const result = 1 + 2;
console.log("Synchronous calculation:", result);

// Asynchronous code - Microtask
Promise.resolve().then(() => {
    console.log("Microtask 1");
});

// Asynchronous code - Macrotask
setTimeout(() => {
    console.log("Macrotask 1");
}, 0);

// More microtasks
Promise.resolve().then(() => {
    console.log("Microtask 2");
});

console.log("End execution");

// Output order:
// Start execution
// Synchronous calculation: 3
// End execution
// Microtask 1
// Microtask 2
// Macrotask 1

// Asynchronous function
async function fetchData() {
    console.log("Start fetching data");
    
    // Simulate network request
    const response = await new Promise(resolve => {
        setTimeout(() => {
            resolve({ data: "Hello from server" });
        }, 1000);
    });
    
    console.log("Data fetched:", response.data);
    return response.data;
}

// Call asynchronous function
fetchData().then(data => {
    console.log("Processing data:", data);
});

console.log("Continue executing other code");

// Concurrent processing (actually concurrency, not parallelism)
async function processItems(items) {
    const promises = items.map(async (item) => {
        // Simulate asynchronous processing
        await new Promise(resolve => setTimeout(resolve, 100));
        return `processed_${item}`;
    });
    
    const results = await Promise.all(promises);
    console.log("All items processed:", results);
}

processItems([1, 2, 3, 4, 5]);
```
</UniversalEditor>

Although JavaScript is single-threaded, multi-threaded concurrency can be achieved through **Web Workers**, which offload time-consuming computation tasks to background threads, preventing the main thread from being blocked. This is similar to Rust's multi-threading, but Web Workers cannot directly share memory and require communication via message passing.

### Rust's Multi-threading Model

Rust supports true multi-threaded parallel execution:

<UniversalEditor title="Rust Multi-threading" compare={true}>
```rust !! rs
use std::thread;
use std::time::Duration;

fn main() {
    println!("Start execution");
    
    // Synchronous code
    let result = 1 + 2;
    println!("Synchronous calculation: {}", result);
    
    // Create thread
    let handle = thread::spawn(|| {
        println!("Thread 1 started");
        thread::sleep(Duration::from_millis(100));
        println!("Thread 1 finished");
    });
    
    // Main thread continues execution
    println!("Main thread continues execution");
    
    // Wait for thread to finish
    handle.join().unwrap();
    println!("All threads finished");
}

// Multi-threaded data processing
fn process_items_parallel(items: Vec<i32>) {
    let handles: Vec<_> = items.into_iter().map(|item| {
        thread::spawn(move || {
            // Simulate processing time
            thread::sleep(Duration::from_millis(100));
            format!("processed_{}", item)
        })
    }).collect();
    
    // Collect results from all threads
    let results: Vec<String> = handles.into_iter()
        .map(|handle| handle.join().unwrap())
        .collect();
    
    println!("All items processed: {:?}", results);
}

// Using thread pool
use std::sync::mpsc;

fn main() {
    let (tx, rx) = mpsc::channel();
    
    // Sender thread
    thread::spawn(move || {
        let messages = vec![
            String::from("Message 1"),
            String::from("Message 2"),
            String::from("Message 3"),
        ];
        
        for msg in messages {
            tx.send(msg).unwrap();
            thread::sleep(Duration::from_millis(100));
        }
    });
    
    // Receiver thread
    for received in rx {
        println!("Received: {}", received);
    }
}
```
</UniversalEditor>

### Execution Model Differences

1. **Single-threaded vs Multi-threaded**: JavaScript single-threaded event loop, Rust supports multi-threaded parallelism
2. **Concurrency vs Parallelism**: JavaScript concurrency not parallelism, Rust can truly parallelize
3. **Memory Safety**: JavaScript runtime checks, Rust compile-time guarantees thread safety
4. **Performance**: JavaScript limited by single-thread, Rust can fully utilize multi-core

---

## 🔒 Thread Safety & Ownership

### Shared State Management

<UniversalEditor title="Thread Safety" compare={true}>
```rust !! rs
use std::sync::{Arc, Mutex};
use std::thread;

// Thread-safe counter
struct SafeCounter {
    count: Mutex<i32>,
}

impl SafeCounter {
    fn new() -> Self {
        SafeCounter {
            count: Mutex::new(0),
        }
    }
    
    fn increment(&self) {
        let mut count = self.count.lock().unwrap();
        *count += 1;
    }
    
    fn get_count(&self) -> i32 {
        *self.count.lock().unwrap()
    }
}

fn main() {
    let counter = Arc::new(SafeCounter::new());
    let mut handles = vec![];
    
    // Create multiple threads to increment counter simultaneously
    for _ in 0..10 {
        let counter = Arc::clone(&counter);
        let handle = thread::spawn(move || {
            for _ in 0..100 {
                counter.increment();
            }
        });
        handles.push(handle);
    }
    
    // Wait for all threads to complete
    for handle in handles {
        handle.join().unwrap();
    }
    
    println!("Final count: {}", counter.get_count()); // Should be 1000
}

// Using RwLock for read/write separation
use std::sync::RwLock;

struct DataStore {
    data: RwLock<Vec<String>>,
}

impl DataStore {
    fn new() -> Self {
        DataStore {
            data: RwLock::new(Vec::new()),
        }
    }
    
    fn write(&self, item: String) {
        let mut data = self.data.write().unwrap();
        data.push(item);
    }
    
    fn read(&self) -> Vec<String> {
        let data = self.data.read().unwrap();
        data.clone()
    }
}

fn main() {
    let store = Arc::new(DataStore::new());
    let mut handles = vec![];
    
    // Writer threads
    for i in 0..5 {
        let store = Arc::clone(&store);
        let handle = thread::spawn(move || {
            store.write(format!("Data {}", i));
        });
        handles.push(handle);
    }
    
    // Reader threads
    for _ in 0..3 {
        let store = Arc::clone(&store);
        let handle = thread::spawn(move || {
            let data = store.read();
            println!("Data read: {:?}", data);
        });
        handles.push(handle);
    }
    
    for handle in handles {
        handle.join().unwrap();
    }
}
```
</UniversalEditor>

---

## ⚡ Asynchronous Programming

### Rust's Asynchronous Programming

<UniversalEditor title="Rust Asynchronous Programming" compare={true}>
```rust !! rs
use tokio;
use std::time::Duration;

// Asynchronous function
async fn fetch_data() -> String {
    println!("Start fetching data");
    
    // Simulate network request
    tokio::time::sleep(Duration::from_secs(1)).await;
    
    println!("Data fetched");
    String::from("Hello from server")
}

// Asynchronous main function
#[tokio::main]
async fn main() {
    println!("Start execution");
    
    // Call asynchronous function
    let data = fetch_data().await;
    println!("Processing data: {}", data);
    
    println!("Continue executing other code");
}

// Concurrent asynchronous tasks
async fn process_items_async(items: Vec<i32>) -> Vec<String> {
    let mut handles = vec![];
    
    for item in items {
        let handle = tokio::spawn(async move {
            // Simulate asynchronous processing
            tokio::time::sleep(Duration::from_millis(100)).await;
            format!("processed_{}", item)
        });
        handles.push(handle);
    }
    
    // Wait for all tasks to complete
    let mut results = vec![];
    for handle in handles {
        let result = handle.await.unwrap();
        results.push(result);
    }
    
    results
}

#[tokio::main]
async fn main() {
    let items = vec![1, 2, 3, 4, 5];
    let results = process_items_async(items).await;
    println!("All items processed: {:?}", results);
}

// Asynchronous channel
use tokio::sync::mpsc;

async fn async_channel_example() {
    let (tx, mut rx) = mpsc::channel(100);
    
    // Sender task
    let producer = tokio::spawn(async move {
        for i in 0..10 {
            tx.send(format!("Message {}", i)).await.unwrap();
            tokio::time::sleep(Duration::from_millis(100)).await;
        }
    });
    
    // Receiver task
    let consumer = tokio::spawn(async move {
        while let Some(message) = rx.recv().await {
            println!("Received: {}", message);
        }
    });
    
    // Wait for both tasks to complete
    let _ = tokio::join!(producer, consumer);
}

#[tokio::main]
async fn main() {
    async_channel_example().await;
}
```
</UniversalEditor>

### Asynchronous vs Multi-threading Comparison

<UniversalEditor title="Async vs Multi-threading" compare={true}>
```rust !! rs
use std::time::Duration;
use tokio;

// Multi-threaded version - suitable for CPU-bound tasks
fn cpu_intensive_task() -> i32 {
    // Simulate CPU-bound computation
    let mut result = 0;
    for i in 0..1_000_000 {
        result += i;
    }
    result
}

fn multi_threaded_example() {
    let start = std::time::Instant::now();
    
    let handles: Vec<_> = (0..4).map(|_| {
        std::thread::spawn(|| {
            cpu_intensive_task()
        })
    }).collect();
    
    let results: Vec<i32> = handles.into_iter()
        .map(|handle| handle.join().unwrap())
        .collect();
    
    let duration = start.elapsed();
    println!("Multi-threaded time: {:?}, Result: {:?}", duration, results);
}

// Asynchronous version - suitable for I/O-bound tasks
async fn io_intensive_task() -> String {
    // Simulate I/O operation
    tokio::time::sleep(Duration::from_millis(100)).await;
    String::from("I/O task complete")
}

async fn async_example() {
    let start = std::time::Instant::now();
    
    let handles: Vec<_> = (0..100).map(|_| {
        tokio::spawn(async {
            io_intensive_task().await
        })
    }).collect();
    
    let results: Vec<String> = futures::future::join_all(handles).await
        .into_iter()
        .map(|r| r.unwrap())
        .collect();
    
    let duration = start.elapsed();
    println!("Async time: {:?}, Processed {} tasks", duration, results.len());
}

#[tokio::main]
async fn main() {
    // Compare both methods
    multi_threaded_example();
    async_example().await;
}
```
</UniversalEditor>

---

## 🎯 Concurrency Patterns Comparison

### JavaScript's Concurrency Patterns

<UniversalEditor title="JavaScript Concurrency Patterns" compare={true}>
```javascript !! js
// JavaScript Concurrency Patterns
class DataStore {
    constructor() {
        this.data = [];
        this.promise = Promise.resolve();
    }
    
    // Use Promise chain to ensure sequential execution
    async write(item) {
        this.promise = this.promise.then(async () => {
            await new Promise(resolve => setTimeout(resolve, 100));
            this.data.push(item);
            console.log(`Write: ${item}`);
        });
        return this.promise;
    }
    
    async read() {
        await this.promise;
        return [...this.data];
    }
}

// Usage example
async function javascript_concurrency() {
    const store = new DataStore();
    
    // Concurrent writes
    const writePromises = [];
    for (let i = 0; i < 5; i++) {
        writePromises.push(store.write(`Data ${i}`));
    }
    
    // Wait for all writes to complete
    await Promise.all(writePromises);
    
    // Read data
    const data = await store.read();
    console.log("Data read:", data);
}

// Worker Threads (similar to Rust's multi-threading)
if (typeof Worker !== 'undefined') {
    const worker = new Worker(`
        self.onmessage = function(e) {
            const result = e.data * 2;
            self.postMessage(result);
        };
    `);
    
    worker.onmessage = function(e) {
        console.log("Worker calculation result:", e.data);
    };
    
    worker.postMessage(42);
}

javascript_concurrency();
```
</UniversalEditor>

### Rust's Concurrency Patterns

<UniversalEditor title="Rust Concurrency Patterns" compare={true}>
```rust !! rs
use std::sync::{Arc, Mutex};
use tokio::sync::RwLock;

// Thread-safe asynchronous data store
struct AsyncDataStore {
    data: Arc<RwLock<Vec<String>>>,
}

impl AsyncDataStore {
    fn new() -> Self {
        AsyncDataStore {
            data: Arc::new(RwLock::new(Vec::new())),
        }
    }
    
    async fn write(&self, item: String) {
        let mut data = self.data.write().await;
        tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
        data.push(item);
        println!("Write: {}", item);
    }
    
    async fn read(&self) -> Vec<String> {
        let data = self.data.read().await;
        data.clone()
    }
}

#[tokio::main]
async fn rust_concurrency() {
    let store = Arc::new(AsyncDataStore::new());
    
    // Concurrent writes
    let mut write_handles = vec![];
    for i in 0..5 {
        let store = Arc::clone(&store);
        let handle = tokio::spawn(async move {
            store.write(format!("Data {}", i)).await;
        });
        write_handles.push(handle);
    }
    
    // Wait for all writes to complete
    for handle in write_handles {
        handle.await.unwrap();
    }
    
    // Read data
    let data = store.read().await;
    println!("Data read: {:?}", data);
}

// Using rayon for parallel computation
use rayon::prelude::*;

fn parallel_computation() {
    let numbers: Vec<i32> = (0..1_000_000).collect();
    
    let start = std::time::Instant::now();
    
    // Parallel computation
    let sum: i64 = numbers.par_iter()
        .map(|&x| x as i64)
        .sum();
    
    let duration = start.elapsed();
    println!("Parallel computation time: {:?}, Result: {}", duration, sum);
}

fn main() {
    // Run asynchronous concurrency example
    rust_concurrency();
    
    // Run parallel computation example
    parallel_computation();
}
```
</UniversalEditor>

---

## 🎯 Exercises

### Exercise 1: Thread-Safe Counter

Create a thread-safe counter that supports multiple threads incrementing the count simultaneously:

<details>
<summary>View Answer</summary>

```rust
use std::sync::{Arc, Mutex};
use std::thread;

struct Counter {
    count: Mutex<i32>,
}

impl Counter {
    fn new() -> Self {
        Counter {
            count: Mutex::new(0),
        }
    }
    
    fn increment(&self) {
        let mut count = self.count.lock().unwrap();
        *count += 1;
    }
    
    fn get_count(&self) -> i32 {
        *self.count.lock().unwrap()
    }
}

fn main() {
    let counter = Arc::new(Counter::new());
    let mut handles = vec![];
    
    for _ in 0..10 {
        let counter = Arc::clone(&counter);
        let handle = thread::spawn(move || {
            for _ in 0..100 {
                counter.increment();
            }
        });
        handles.push(handle);
    }
    
    for handle in handles {
        handle.join().unwrap();
    }
    
    println!("Final count: {}", counter.get_count()); // Should be 1000
}
```

</details>

### Exercise 2: Asynchronous Task Processing

Create an asynchronous function that concurrently processes multiple tasks and collects the results:

<details>
<summary>View Answer</summary>

```rust
use tokio;
use std::time::Duration;

async fn process_task(id: i32) -> String {
    tokio::time::sleep(Duration::from_millis(100)).await;
    format!("Task {} complete", id)
}

async fn process_all_tasks() -> Vec<String> {
    let mut handles = vec![];
    
    for i in 0..10 {
        let handle = tokio::spawn(async move {
            process_task(i).await
        });
        handles.push(handle);
    }
    
    let mut results = vec![];
    for handle in handles {
        let result = handle.await.unwrap();
        results.push(result);
    }
    
    results
}

#[tokio::main]
async fn main() {
    let results = process_all_tasks().await;
    println!("All tasks complete: {:?}", results);
}
```

</details>

### Exercise 3: Producer-Consumer Pattern

Implement a producer-consumer pattern using channels for inter-thread communication:

<details>
<summary>View Answer</summary>

```rust
use std::sync::mpsc;
use std::thread;
use std::time::Duration;

fn producer_consumer() {
    let (tx, rx) = mpsc::channel();
    
    // Producer
    let producer = thread::spawn(move || {
        for i in 0..10 {
            tx.send(format!("Product {}", i)).unwrap();
            thread::sleep(Duration::from_millis(100));
        }
    });
    
    // Consumer
    let consumer = thread::spawn(move || {
        for received in rx {
            println!("Consumed: {}", received);
        }
    });
    
    producer.join().unwrap();
    consumer.join().unwrap();
}

fn main() {
    producer_consumer();
}
```

</details>

---

## 📝 Summary

In this chapter, we learned about Rust's concurrency and asynchronous programming:

1. **Execution Model**: Rust supports true multi-threaded parallelism, JavaScript is single-threaded event loop
2. **Thread Safety**: Rust guarantees thread safety at compile time through the ownership system
3. **Asynchronous Programming**: Rust's async/await syntax is similar to JavaScript
4. **Concurrency Patterns**: Safely share state using types like Arc, Mutex, RwLock
5. **Performance Choice**: Multi-threading for CPU-bound, asynchronous for I/O-bound

### Key Takeaways

- Rust's ownership system ensures thread safety
- Asynchronous programming provides high-performance I/O handling
- Choosing the right concurrency model is important
- Compile-time checks prevent runtime errors

### Next Steps

In the next chapter, we will learn about Rust's type system and traits, and how to build reusable abstractions.

---

**Continue Learning**: [Type System & Traits](./module-05-type-system-traits)